package com.shuai.user.service.impl;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.utils.StringUtils;
import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenRequest;
import com.aliyun.dingtalkoauth2_1_0.models.GetUserTokenResponse;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.shuai.common.constant.AuthenticationConstant;
import com.shuai.common.constant.ErrorCode;
import com.shuai.common.constant.GenderEnum;
import com.shuai.common.constant.UserConstant;
import com.shuai.common.exception.BusinessException;
import com.shuai.common.utils.MyJWTUtil;
import com.shuai.common.utils.PasswordUtil;
import com.shuai.user.annotation.LoginStrategyService;
import com.shuai.user.constant.LoginTypeEnum;
import com.shuai.user.domain.dto.DingDingUserDTO;
import com.shuai.user.domain.entity.User;
import com.shuai.user.service.LoginBaseService;
import com.shuai.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Objects;
import java.util.Random;
import java.util.UUID;

@LoginStrategyService
@Service
public class DingdingScanCodeLoginServiceImpl implements LoginBaseService {


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private UserService userService;

    private static final Object lock = new Object();

    @Override
    public User login(Object request, HttpServletResponse response) throws Exception {
        com.aliyun.dingtalkoauth2_1_0.Client client = authClient();
        GetUserTokenRequest getUserTokenRequest = new GetUserTokenRequest()

                //应用基础信息-应用信息的AppKey,请务必替换为开发的应用AppKey
                .setClientId("dingl7oimbjxovn7ccu1")

                //应用基础信息-应用信息的AppSecret，,请务必替换为开发的应用AppSecret
                .setClientSecret("YOmciZJXYUEB9f9hRVSq6F6v5Mk0h6kd9LHofiTAniRVNoavlH9Ucyb2J6hTC64L")
                .setCode((String) request)
                .setGrantType("authorization_code");
        GetUserTokenResponse getUserTokenResponse = client.getUserToken(getUserTokenRequest);
        //获取用户个人token
        String accessToken = getUserTokenResponse.getBody().getAccessToken();
        String userinfo = getUserinfo(accessToken);
        if (StringUtils.isBlank(userinfo)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "钉钉用户授权失败");
        }
        // 拿到了扫码登录的用户信息
        DingDingUserDTO dingDingUserDTO = JSONUtil.toBean(userinfo, DingDingUserDTO.class);
        User loginUser = this.login(dingDingUserDTO);
        HashMap<String, Object> payload = new HashMap<>();
        // 添加JWT鉴权信息
        payload.put(AuthenticationConstant.PAYLOAD_USERID, loginUser.getId());
        response.setHeader(AuthenticationConstant.AUTHENTICATION_HEADER, MyJWTUtil.createJWT(payload));
        return loginUser;
    }


    @Override
    public LoginTypeEnum getLoginEnumType() {
        return LoginTypeEnum.DINGDING_SCAN_CODE;
    }


    public static com.aliyun.dingtalkcontact_1_0.Client contactClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalkcontact_1_0.Client(config);
    }

    /**
     * 获取用户个人信息
     */
    public String getUserinfo(String accessToken) throws Exception {
        com.aliyun.dingtalkcontact_1_0.Client client = contactClient();
        GetUserHeaders getUserHeaders = new GetUserHeaders();
        getUserHeaders.xAcsDingtalkAccessToken = accessToken;
        //获取用户个人信息，如需获取当前授权人的信息，unionId参数必须传me
        return JSON.toJSONString(client.getUserWithOptions("me", getUserHeaders, new RuntimeOptions()).getBody());
    }


    public static com.aliyun.dingtalkoauth2_1_0.Client authClient() throws Exception {
        Config config = new Config();
        config.protocol = "https";
        config.regionId = "central";
        return new com.aliyun.dingtalkoauth2_1_0.Client(config);
    }

    private User login(DingDingUserDTO dingDingUserDTO) {
        synchronized (lock) {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<User>().eq(User::getMobile, dingDingUserDTO.getMobile());
            User exists = userService.getOne(queryWrapper);
            if (!Objects.isNull(exists)) {
                exists.setPassword("");
                this.setLoginState(exists, stringRedisTemplate);
                return exists;
            }
            User build = User.builder()
                    .gender(GenderEnum.UNDISCLOSED.getCode())
                    .header(dingDingUserDTO.getAvatarUrl())
                    .mobile(dingDingUserDTO.getMobile())
                    .password(PasswordUtil.encryptPwd(dingDingUserDTO.getMobile()))
                    .nickname(UserConstant.DEFAULT_USERNAME_PREFIX + new Random().nextLong())
                    .username(dingDingUserDTO.getNick())
                    .apiKey(UUID.randomUUID().toString().replaceAll("-", ""))
                    .apiSecret(UUID.randomUUID().toString().replaceAll("-", "")).build();
            if (!userService.save(build)) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户注册失败,请稍后重试");
            }
            build = userService.getById(build.getId());
            build.setPassword("");
            this.setLoginState(build, stringRedisTemplate);
            return build;
        }
    }
}
